/**
 * Copyright 2018 orivil.com. All rights reserved.
 * Use of this source code is governed by a MIT-style
 * license that can be found at https://mit-license.org.
 */

package model

import (

	"os"
	"fmt"
	"gitee.com/tugoer/orivil/config"
	"gitee.com/tugoer/orivil/log"
	"runtime"
	"time"
	"strconv"
	"gitee.com/tugoer/psy-testing/code/sites/quce_la"
	"gitee.com/tugoer/psy-testing/code/sites"
	"gitee.com/tugoer/psy-testing/code/env"
	"encoding/json"
)

const (
	imagesDir = "images"
	generateDir = "images/generate"
)

const (
	QRSize = 120
	QRFontSize = 20
)

const (
	QrCodeUrl = "http://testing.cqcq668.cn"
	TickerWaitMinute = 10 //
	DownloadHourTime = 4 // 凌晨4点开始抓取最新数据
)

func init() {
	err := os.MkdirAll(generateDir, 0777)
	if err != nil {
		panic(err)
	}
	env.GormDB.AutoMigrate(
		&Subject{},
		&Result{},
		&Admin{},
		&Spoof{},
	)
	var adminNum int
	err = env.GormDB.Model(&Admin{}).Count(&adminNum).Error
	if err != nil {
		panic(err)
	}
	fmt.Println(adminNum)
	if adminNum == 0 {
		var ads = []*Admin{{}}
		parser := config.NewJsonParser("configs")
		err = parser.ReadOrCreate("admins", &ads)
		if err != nil {
			panic(err)
		}
		if len(ads) == 0 || ads[0].Name == "" {
			panic("未设置超级管理员")
		} else {
			for _, a := range ads {
				err = a.Create()
				if err != nil {
					panic(err)
				}
			}
		}
	}
}

func AutoDownloadLatest()  {
	go func() {
		defer func() {
			e := recover()
			if e != nil {
				const size = 64 << 10
				buf := make([]byte, size)
				buf = buf[:runtime.Stack(buf, false)]

				log.Emergency.Printf("panic: %s\n 自动更新进程出错：%v\n", string(buf), e)
			}
		}()
		err := DownloadLatest()
		if err != nil {
			panic(err)
		}
		ticker := time.NewTicker(TickerWaitMinute * time.Minute)
		for t := range ticker.C {
			// 每天定时抓取最新的数据，并初始化
			if t.Hour() == DownloadHourTime && t.Minute() <= TickerWaitMinute {
				err := DownloadLatest()
				if err != nil {
					log.Emergency.Printf("自动更新数据时出错：%s\n", err)
				}
			}
		}
	}()
}

func DownloadLatest() error {
	sub := GetLastSubject()
	var lastSub int
	if sub != nil {
		var err error
		lastSub, err = strconv.Atoi(sub.OriginalID)
		if err != nil {
			return err
		}
	}
	quce_la.DownloadLatest(lastSub, imagesDir, func(sub *quce_la.Subject, ress map[string]*quce_la.Result) {
		questions, err := json.Marshal(sub.Questions)
		if err != nil {
			log.Warning.Printf("marshal subject [%s] questions got error:%s", sub.ID, err)
		}
		typ, err := strconv.Atoi(sub.Type)
		if err != nil {
			log.Warning.Printf("transform subject [%s] type got error:%s", sub.ID, err)
		}
		cid, err := strconv.Atoi(sub.Cid)
		if err != nil {
			log.Warning.Printf("transform subject [%s] cid got error:%s", sub.ID, err)
		}
		view, err := strconv.Atoi(sub.View)
		if err != nil {
			log.Warning.Printf("transform subject [%s] view got error:%s\n", sub.ID, err)
		}
		top, err := strconv.Atoi(sub.Top)
		if err != nil {
			log.Warning.Printf("transform subject [%s] top got error:%s\n", sub.ID, err)
		}
		likeNum, err := strconv.Atoi(sub.LikeNum)
		if err != nil {
			log.Warning.Printf("transform subject [%s] likenum got error:%s\n", sub.ID, err)
		}
		uniux, err := strconv.ParseInt(sub.Utime, 10, 64)
		if err != nil {
			log.Warning.Printf("transform subject [%s] utime got error:%s\n", sub.ID, err)
		}
		utime := time.Unix(uniux, 0)
		msub := &Subject {
			OriginalID: sub.ID,
			Title:      sub.Title,
			Logo:       sub.Logo,
			Description:       sub.Desc,
			Questions:  string(questions),
			Type:       typ,
			Cid:        cid,
			Img:        sub.Img,
			View:       view,
			Top:        top,
			LikeNum:    likeNum,
			CreatedAt:  &utime,
		}
		time.Sleep(10 * time.Millisecond)
		err = msub.Create()
		if err != nil {
			log.Warning.Printf("create subject [%s] got error:%s\n", sub.ID, err)
		}
		for answer, res := range ress {
			// 生成二维码图片，如果图片已存在则跳过
			qrcodeImg, err := sites.GenerateQrcode(
				QRSize,
				QRFontSize,
				sub.ID,
				sub.Title,
				generateDir,
				answer,
				QrCodeUrl,
				res.Content.Img,
			)
			if err != nil {
				log.Warning.Printf("subject answer [%s.%s] generate qrcode got error:%s\n", sub.ID, answer, err)
			}
			result := &Result {
				SubjectID: sub.ID,
				Answer:    answer,
				MaxWeight: res.MaxWeight,
				MinWeight: res.MinWeight,
				SrcImage:  res.Content.Img,
				Image:     qrcodeImg,
				Title:     res.Content.Title,
				Content:   res.Content.Desc,
			}
			time.Sleep(10 * time.Millisecond)
			err = result.Create()
			if err != nil {
				log.Warning.Printf("create subject answer [%s.%s] got error:%s\n", sub.ID, answer, err)
			}
		}
	})
	return nil
}
